<?php

namespace common\service;


use common\model\PlaylistVersionModel;
use common\model\EntityModel;
use support\SingletonTrait;
use think\module\Module;
use Exception;

class EpisodeShowingsNumberTreeService
{
    use SingletonTrait;

    public function __construct()
    {
    }

    /**
     * 给集数列表数据追加剧本、台词本上传状态判断数据
     * @return void
     */
    private function appendEpisodeScriptData(&$episodeList)
    {
        $episodeIds = array_column($episodeList, "id");
        $scriptRequestData = [
            'param' => [
                'filter' => ['episode_id' => ["-in", $episodeIds]],
                'fields' => 'episode_id,project_id'
            ]
        ];
        $scriptResData = teamones_request('teamones-script', 'script/select', $scriptRequestData)['data'];
        $scriptLineResData = teamones_request('teamones-script', 'script_line/select', $scriptRequestData)['data'];
        $episodeMap = [
            'script' => array_column($scriptResData, 'episode_id', 'episode_id'),
            'script_line' => array_column($scriptLineResData, 'episode_id', 'episode_id'),
        ];

        $episodeList = array_map(function ($episodeItem) use ($episodeMap) {
            $episodeItem['is_up_script'] = isset($episodeMap['script'][$episodeItem['id']]);
            $episodeItem['is_up_script_line'] = isset($episodeMap['script_line'][$episodeItem['id']]);
            return $episodeItem;
        }, $episodeList);
    }

    /**
     * 根据集所属状态获取集数列表
     * @param $projectId
     * @param $episodeStatus
     * @param $countType
     * @param $userId
     * @param $page
     * @param $onlyShowResponsible
     * @param $onlyShowResponsibleFilter
     * @return array|mixed|string
     */
    public function getEpisodeList($projectId, $episodeStatus, $countType, $userId, $page = [], $onlyShowResponsible = false, $onlyShowResponsibleFilter = '')
    {
        // 1.组装过滤条件
        $filter = [
            'project_id' => $projectId,
            'module_id' => Module::$moduleDictData['module_index_by_code']['episode']['id'],
        ];

        // 1.1 是否指定获取集数状态数据列表
        switch ($episodeStatus) {
            case 'inprogress':
                // 仅获取进行中的集数
                $filter[] = [
                    "_string" => "JSON_UNQUOTE(JSON_EXTRACT(json, '$.episode_is_seal')) IS NULL",
                    "JSON_UNQUOTE(JSON_EXTRACT(json, '$.episode_is_seal'))" => 'no',
                    "_logic" => "or"
                ];
                break;
            case 'done':
                // 仅获取已完成的集数
                $filter["JSON_UNQUOTE(JSON_EXTRACT(json, '$.episode_is_seal'))"] = 'yes';
                break;
            default:
                // 默认取所有状态集数
                break;
        }

        // 1.2 完善过滤条件，仅显示我负责的集数数据
        // $onlyShowResponsibleFilter 传参是过滤集数范围权限类型
        if ($onlyShowResponsible) {
            $episodeExtraFilter = $this->getEpisodeExtraFilterByDataFilter($onlyShowResponsibleFilter, $filter['project_id'], $userId);
            if (!empty($episodeExtraFilter)) {
                $filter[] = $episodeExtraFilter;
            }
        }

        // 2.查询集数列表数据
        $fields = [
            'id',
            'name',
            'code',
            "json->>'$.episode_is_seal' as episode_is_seal"
        ];


        $episodeQuery = model(EntityModel::class)
            ->where($filter)
            ->field($fields);

        if (!empty($page)) {
            $episodeQuery->page($page[0], $page[1]);
        }
        $episodeList = $episodeQuery->order("code ASC")->select();

        if (empty($episodeList)) {
            return [];
        }

        // 3.判断是否需要统计
        if ($countType !== 'none') {
            switch ($countType) {
                case 'script_up':
                    // 获取剧本数据上传数据统计
                    $this->appendEpisodeScriptData($episodeList);
                    break;
                default:
                    // 默认不格式化数据
                    break;
            }
        }

        return $episodeList;
    }

    /**
     * 根据集数ID获取场次列表
     * @param $projectId
     * @param $episodeId
     * @return array
     */
    public function getShowingNumberListByEpisode($projectId, $episodeId)
    {
        // 请求剧本数据集获取场次数据
        $showingNumberList = $this->sceneSelect([
            'project_id' => $projectId,
            'episode_id' => $episodeId
        ], 'id,name');

        if (empty($showingNumberList)) {
            return [];
        }
        return $showingNumberList;
    }

    /**
     * 查询集场树
     * @param $filter
     * @param int $userId
     * @param int $episodeChunkSize
     * @param bool $showTotal
     * @param $dataFilter
     * @param bool $includeShowingsNumber
     * @param $countDataSource
     * @param $entityDataFilter
     * @param $isQueryUp
     * @return array|false|mixed|string
     */
    public function episodeShowingNumberTree($filter, int $userId, int $episodeChunkSize = 0, bool $showTotal = true, $dataFilter = null, bool $includeShowingsNumber = true, $countDataSource = null, $entityDataFilter = null, $isQueryUp = null)
    {
        $episodeListFilter = [
            'project_id' => $filter['project_id'],
            'module_id' => Module::$moduleDictData['module_index_by_code']['episode']['id'],
        ];

        if (!empty($filter['code'])) {
            $episodeListFilter['code'] = $filter['code'];
        }
        if (!empty($filter['episode_is_seal']) && $filter['episode_is_seal'] == 'yes') {
            $episodeListFilter["JSON_UNQUOTE(JSON_EXTRACT(json, '$.episode_is_seal'))"] = 'yes';
        }

        if (!$showTotal) {
            $episodeExtraFilter = $this->getEpisodeExtraFilterByDataFilter($dataFilter, $filter['project_id'], $userId);
            if (!empty($episodeExtraFilter)) {
                $episodeListFilter[] = $episodeExtraFilter;
            }
        }

        $episodeList = model(EntityModel::class)
            ->where($episodeListFilter)
            ->field("id,name,code,'episode' as type,json->>'$.episode_status' as episode_status,json->>'$.episode_is_show' as episode_is_show,json->>'$.episode_is_seal' as episode_is_seal")
            ->order("code ASC")
            ->select();

        //查询是否上传过剧本、台词本
        if ($isQueryUp == "yes" && !empty($episodeList)) {
            $episodeIds = array_column($episodeList, "id");
            $scriptRequestData = [
                'param' => [
                    'filter' => ['episode_id' => ["-in", $episodeIds]],
                    'fields' => 'episode_id,project_id'
                ]
            ];
            $scriptResData = teamones_request('teamones-script', 'script/select', $scriptRequestData)['data'];
            $scriptLineResData = teamones_request('teamones-script', 'script_line/select', $scriptRequestData)['data'];
            $episodeMap = [
                'script' => array_column($scriptResData, 'episode_id', 'episode_id'),
                'script_line' => array_column($scriptLineResData, 'episode_id', 'episode_id'),
            ];

            $episodeList = array_map(function ($episodeItem) use ($episodeMap) {
                $episodeItem['is_up_script'] = isset($episodeMap['script'][$episodeItem['id']]);
                $episodeItem['is_up_script_line'] = isset($episodeMap['script_line'][$episodeItem['id']]);
                return $episodeItem;
            }, $episodeList);
        }

        if ($includeShowingsNumber && !empty($episodeList)) {
            $showingNumberList = $this->sceneSelect(['project_id' => $filter['project_id'],]);
            $showingNumberList = array_group_by($showingNumberList, 'episode_id');

            foreach ($episodeList as &$episode) {
                $episode['children'] = $showingNumberList[$episode['id']] ?? [];
                $episode['children'] = array_values(array_sort_by($episode['children'], 'name'));
                $episode['children'] = array_map(function ($item) use ($episode) {
                    $item['scene_id'] = $item['id'];
                    $item['id'] = $episode['code'] . '_' . $item['name'];
                    $item['code'] = $item['name'];
                    $item['type'] = 'showings_number';
                    $item['parent_code'] = $episode['code'];
                    $item['parent_id'] = $episode['id'];
                    unset($item['episode_code'], $item['unique_name']);
                    return $item;
                }, $episode['children']);
            }
        }

        if (!empty($entityDataFilter)) {
            $episodeCodes = array_column($episodeList, "code");
            $entityEpisodeCode = $this->episodeEntityDataFilter($episodeCodes, $entityDataFilter, $filter['project_id']);
            $episodeList = array_filter($episodeList, function ($episodeItem) use ($entityEpisodeCode) {
                return in_array($episodeItem["code"], $entityEpisodeCode);
            });
        }

        if ($episodeChunkSize > 1) {
            $res = $this->buildEpisodeCollection($episodeList, $episodeChunkSize);
        } else {
            $res = $episodeList;
        }
        return $res;
    }

    /**
     * 集信息分段
     * @param array $episodeList
     * @param int $chunkSize
     * @return array
     */
    public function buildEpisodeCollection(array $episodeList, int $chunkSize)
    {
        $res = [];
        $episodeList = array_chunk($episodeList, $chunkSize);
        foreach ($episodeList as $index => $episodeListItem) {
            if (count($episodeListItem) > 1) {
                $tmp = [
                    'id' => "episode_collections$index",
                    'name' => $episodeListItem[0]['name'] . '-' . $episodeListItem[count($episodeListItem) - 1]['name'],
                    'code' => array_column($episodeListItem, 'code'),
                    'type' => 'episode_collection',
                    'children' => $episodeListItem
                ];
            } else {
                $tmp = $episodeListItem[0];
            }
            $res[] = $tmp;
        }
        return $res;
    }

    /**
     * 实体数据筛选
     * @param $episodeCodes
     * @param $entityDataFilter
     * @param $projectId
     * @return array
     */
    public function episodeEntityDataFilter($episodeCodes, $entityDataFilter, $projectId)
    {
        if (!empty($episodeCodes)) {
            $entityModuleId = [];
            if ($entityDataFilter == "shot") {
                $entityModuleId = [module_by_code("shot")["id"]];
            } elseif ($entityDataFilter == "asset") {
                $entityModuleId = [module_by_code("asset")["id"], module_by_code("level")["id"]];
            }

            if (!empty($entityModuleId)) {
                $initialEpisodeCodes = model(EntityModel::class)->where([
                    "project_id" => $projectId,
                    "module_id" => ["IN", $entityModuleId],
                    "initial_episode_code" => ["IN", $episodeCodes]
                ])->field("initial_episode_code")->group("initial_episode_code")->select();
                return array_column($initialEpisodeCodes, "initial_episode_code");
            }
        }
        return $episodeCodes;
    }

    /**
     * 查询集额外筛选条件
     * @param $dataFilter
     * @param $projectId
     * @param $userId
     * @return array|array[]
     */
    private function getEpisodeExtraFilterByDataFilter($dataFilter, $projectId, $userId)
    {
        $episodeFilter = [];

//        $stepCategoryList = null;
//        if (!empty($moduleCode)) {
//            $stepCategoryList = $this->stepService->getStepCategoryByMergeModuleConfig($moduleCode, false);
//        }

        switch ($dataFilter) {
            // 利用不同的场景 筛选不同的集信息
//            case 'leader_assign_list':
//                /**
//                 * 组装分配列表
//                 * 使用任务分配人筛选
//                 */
//                $taskFilter = [
//                    'project_id' => $projectId,
//                    'assignee' => $userId,
//                ];
//                if (!empty($stepCategoryList)) {
//                    $taskFilter['step_category_id'] = ['IN', array_column($stepCategoryList, 'id')];
//                }
//                $entityIdSubQuery = model(TaskModel::class)->where($taskFilter)->field('entity_id')->group('entity_id')->buildSql();
//                $episodeCodeList = model(EntityModel::class)
//                    ->where('id in ' . $entityIdSubQuery)
//                    ->group('initial_episode_code')->field('initial_episode_code as code')->select();
//                $episodeCodeList = array_filter(array_column($episodeCodeList, 'code'), function ($item) {
//                    return !empty($item);
//                });
//                if (count($episodeCodeList)) {
//                    $episodeFilter = [
//                        'code' => ['IN', $episodeCodeList]
//                    ];
//                }
//                break;
//            case 'task_review_list':
//                /**
//                 * 任务审核列表 使用任务审核人进行筛选
//                 */
//                $versionModuleId = Module::$moduleDictData['module_index_by_code']['version']['id'];
//                $taskModuleId = Module::$moduleDictData['module_index_by_code']['task']['id'];
//                $episodeCodeFilter = [
//                    'e.project_id' => $projectId,
//                ];
//                if (count($stepCategoryList) > 0) {
//                    $episodeCodeFilter['t.step_category_id'] = ['IN', array_column($stepCategoryList, 'id')];
//                }
//                $episodeCodeList = model(EntityModel::class)
//                    ->alias('e')
//                    ->join('task t on t.entity_id = e.id')
//                    ->join("version v on v.module_id = {$taskModuleId} and v.link_id = t.id")
//                    ->join("review_request rr on rr.module_id = {$versionModuleId} and rr.link_id = v.id")
//                    ->join('review_request_node rrn ON rrn.review_request_id = rr.id and rrn.plan_reviewer = ' . $userId)
//                    ->where($episodeCodeFilter)
//                    ->field('initial_episode_code as code')
//                    ->group('initial_episode_code')
//                    ->select();
//                $episodeCodeList = array_filter(array_column($episodeCodeList, 'code'), function ($item) {
//                    return !empty($item);
//                });
//                if (count($episodeCodeList)) {
//                    $episodeFilter = [
//                        'code' => ['IN', $episodeCodeList]
//                    ];
//                }
//                break;
//            case 'myself_task_list':
//                /**
//                 * 我的任务列表
//                 */
//                $taskFilter[] = [
//                    'executor' => $userId,
//                ];
//                $episodeCodeFilter = [
//                    't.project_id' => $projectId,
//                    't.executor' => $userId
//                ];
//
//                if (!empty($stepCategoryList)) {
//                    $episodeCodeFilter['t.step_category_id'] = ['IN', array_column($stepCategoryList, 'id')];
//                }
//
//                $episodeCodeList = model(EntityModel::class)
//                    ->alias('e')
//                    ->join('task t on t.entity_id = e.id')
//                    ->where($episodeCodeFilter)
//                    ->field('initial_episode_code as code')
//                    ->group('initial_episode_code')
//                    ->select();
//                $episodeCodeList = array_filter(array_column($episodeCodeList, 'code'), function ($item) {
//                    return !empty($item);
//                });
//                if (count($episodeCodeList)) {
//                    $episodeFilter = [
//                        'code' => ['IN', $episodeCodeList]
//                    ];
//                }
//                break;
            case 'episode_allocation':
                // 默认剧集分配筛选
                $epAllocationList = EpisodeAllocationService::getInstance()->selectEpisodeAllocations(['project_id' => $projectId, 'user_id' => $userId]);
                if (count($epAllocationList) > 0) {
                    $entityIdList = array_column($epAllocationList, 'entity_id', 'entity_id');
                    $episodeFilter = ['id' => ['IN', array_values($entityIdList)]];
                } else {
                    // 没有任何权限
                    $episodeFilter = ['id' => 0];
                }
                break;
            default:

        }

        return $episodeFilter;
    }

    /**
     * 查询场次
     * @param array $filter
     * @param $fields
     * @return array|mixed
     */
    public function sceneSelect(array $filter, $fields = '')
    {
        $requestData = [
            'param' => [
                'filter' => $filter,
                'fields' => $fields
            ],
        ];
        $res = teamones_request('teamones-script', 'scene/select', $requestData);
        return $res['data'] ?? [];
    }
}
